package com.android.camera.ui;

import com.android.camera.Log;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.Display;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

	/**
	 * ArcSeekBar
	 * 
	 * @author xiaodong.cheng
	 *
	 */
public class RGK_ArcSeekBar extends LinearLayout {

	//private Context mContext;
    private String mKey;
    private Paint drawArc;
    private Paint drawDot;
    private CenterPoint mCpoint;
    private Paint drawCircle;
    private float mCircleradius = 300;
    private int mPadding = 75;
    private RectF rectF;
    private float mDotPosition = 0;
    private int mDotRadius = 46;
    private float mThumbX;
    private float mThumbY;
    private double thumbradius;
    private final static float START_ARC = 247;
    private final static float END_ARC = 46;
    private final static float ALL_ARC = 360;
    //private int mDotColor;
    private double angle;
    private int view = 425;
    private Paint drawArcShaper;
    private int fromColor;
    private int toColor;
    private boolean isNeedShaper;
    private float[] xy;
    private String flag = "";
    private Paint paint_string;
    private boolean mIsDragging;
    private boolean fromUser = false;    //the change from user
    private Drawable mIcon;
    private Drawable mLine;
    private Bitmap mIconBitmap;
    //cheng
    private Display mDisplay;
    private double displayRatio;
    private static float f = 0.1f;
    /**
     * Whether this is user arcSeekable.
     */
    boolean mIsUserSeekable = true;
    RGK_ArcSeekBar.CenterPoint centerPoint = new CenterPoint();
    

    {
    	initPaint();
        centerPoint.x = 305 + 55 + 0;
        centerPoint.y = 310 + 55 + 625;
        setCenterPoint(centerPoint);
        setCenterCircleRadius(868);
        setCenterCircleColorBackground(Color.RED);
        setArcColorBackground(Color.BLUE);
        setArcStrokeWidth(5, true);
        setCenterCirclePadding(65);
        setDotCircleRadius(46);
        setDotColorBackground(Color.GREEN);
        setDotPosition(7.5f);
        setArcShaperColor(Color.BLACK, Color.RED, true);
        doDraw();
    }
    
    public void setKey(String key) {
    	mKey = key;
    }
    
    public String getKey() {
    	return mKey;
    }
    
    public void setDisplay(Display display) {
    	mDisplay = display;
    	int shortLen = display.getWidth() < display.getHeight() ? display.getWidth() : display.getHeight();
		displayRatio  = shortLen/720.0;
    	Log.i("ARC_mDisplay", displayRatio+"");
    }
    
    public RGK_ArcSeekBar(Context context) {
            super(context);
            //this.mContext = context;
            initPaint();
    }

    public RGK_ArcSeekBar(Context context, AttributeSet set) {
            super(context, set);
            //this.mContext = context;
            initPaint();
    }

    @Deprecated
    private RGK_ArcSeekBar(Context context, AttributeSet set, float viewsize) {
            super(context, set);
//	                this.mContext = context;
//	                view = (int) viewsize;
//	                initPaint();
    }

    @SuppressLint("NewApi")
	public RGK_ArcSeekBar(Context context, AttributeSet set, int defStyle) {
            super(context, set, defStyle);
            //this.mContext = context;
            initPaint();
        	
    }

    // use Paint in this
    private void initPaint() {
            setBackgroundColor(Color.TRANSPARENT);
            setGravity(Gravity.CENTER);

            // all Paint will be init and must be setAntis
            drawArc = new Paint();
            drawArc.setAntiAlias(true);
            drawArcShaper = new Paint();
            drawArcShaper.setAntiAlias(true);
            drawCircle = new Paint();
            drawCircle.setAntiAlias(true);
            drawDot = new Paint();
            drawDot.setAntiAlias(true);
            paint_string = new Paint();
    }

    /**
     * setCenterView
     * 
     * @param view
     */
    public void setChildView(View view) {

    }

    /**
     * setCenterViewId
     * 
     * @param id
     */
    public void setChildView(int id) {

    }

    /**
     * setDataObj
     * 
     * @param obj
     */
    public void setDataObj(Object obj) {

    }

    /**
     * ArcShaperColor
     * 
     * @param fromColor
     * @param toColor
     */
    public void setArcShaperColor(int fromColor, int toColor, boolean isNeed) {
    	
            this.fromColor = fromColor;
            this.toColor = toColor;
            this.isNeedShaper = isNeed;
            // getBase Dot
            this.xy = goQuadrant(START_ARC);
    }

    /**
     * setDotCircleRadius
     * 
     * @param radius
     */
    public void setDotCircleRadius(int radius) {
    	// remove temply by anxiang.xiao 
    	/*
            if (mDotRadius >= mPadding) {
                    throw new RuntimeException(
                                    "The radius must be less than padding param");
            }*/
            this.mDotRadius = radius;
    }

    /**
     * setArcStrokeWidth
     * 
     * @param px
     * @param isNeed
     */
    public void setArcStrokeWidth(int px, boolean isNeed) {
    	    
            if (isNeed) {
                    drawArc.setStyle(Paint.Style.STROKE);
                    drawArc.setStrokeWidth(px);
                    drawArcShaper.setStyle(Paint.Style.STROKE);
                    drawArcShaper.setStrokeWidth(px + 2);
            }
    }

    /**
     * setDotColorBackground
     * 
     * @param color
     */
    public void setDotColorBackground(int color) {
            //this.mDotColor = color;
            drawDot.setColor(color);
    }
    
    /**
     * getDotPositon
     * 
     * @return
     */
    public float getDotPosition() {
 	   
 	   return mDotPosition;
    }

    /**
     * getProgress
     * 
     * @return
     */
    public int getProgress() {
    	
    	if(mDotPosition < 7.5) {
    		return 0;
    	}
    	if(mDotPosition > 100-7.5) {
    		return 100;
    	}
    	double ratio = 100f/(100f-7.5*2);
    	int progress = (int) ((mDotPosition-7.5f)*ratio);
    	return progress;
    }
    
    /**
     * setDotPosition
     * 
     * @param position
     */
    public void setDotPosition(float position) {
    	
            if (position > 100) {
                    position = 100;
            }
            if (position < 0) {
                    position = 0;
            }
            this.mDotPosition = position;
           // dotPosition = position;
            initDataforThumb();
    }
    
    /**
     * setProgress
     * 
     * @param progrss
     */
    public void setProgress(int progress) {
    	double ratio = 100f/(100f-7.5*2);
    	float position = (float)(progress/ratio+7.5f);
    	setDotPosition(position);
    }

    
    // initDataforThumb move Dot to x y
    private void initDataforThumb() {
            double proportion = (double) (END_ARC / 100f);
            thumbradius = proportion * mDotPosition;
            getPoint(thumbradius, 0);
    }

    // get Quadrant return is DotCircle circle dot
    private float[] goQuadrant(double thumbradius) {
            float a[] = new float[2];
            float arcradius = mCircleradius + mPadding;
            a[0] = arcradius * (float) Math.sin(Math.toRadians(thumbradius));
            a[1] = arcradius * (float) Math.cos(Math.toRadians(thumbradius));
            return a;
    }

    /**
     * setArcColor
     * 
     * @param color
     */
    public void setArcColorBackground(int color) {
            drawArc.setColor(color);
    }

    /**
     * setCenterCircleColor
     * 
     * @param color
     */
    public void setCenterCircleColorBackground(int color) {
            drawCircle.setColor(color);
    }

    /**
     * setCenterPoint
     * 
     * @param point
     */
    public void setCenterPoint(CenterPoint point) {
            this.mCpoint = point;
    }

    /**
     * setCenterCircleRadius
     * 
     * @param radius
     */
    public void setCenterCircleRadius(float radius) {
            this.mCircleradius = radius;
    }

    /**
     * setCenterCirclePadding
     * 
     * @param padding
     */
    public void setCenterCirclePadding(int padding) {
            this.mPadding = padding;
    }

    /**
     * do OnDraw(Canvas canvas)
     */
    public void doDraw() {
            rectF = new RectF();
            rectF.top = mCpoint.y - (mCircleradius + mPadding);
            rectF.left = mCpoint.x - (mCircleradius + mPadding);
            rectF.right = mCpoint.x + mCircleradius + mPadding;
            rectF.bottom = mCpoint.y + mCircleradius + mPadding;
            invalidate();
    }

    @SuppressLint("ClickableViewAccessibility")
    //int pos = 0;
	@Override
    public boolean onTouchEvent(MotionEvent event) {    	
            if (!mIsUserSeekable || !isEnabled()) {
                return false;
            }
            
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                    if (isTouchThumb(event.getX(), event.getY())) {
                           //drawDot.setColor(Color.BLUE);
                    	onStartTrackingTouch();
                        return true;
                    }
                    return false;
            case MotionEvent.ACTION_MOVE:
            	    if(mIsDragging) {
            	    	fromUser = true;
                	   // pos = (int)((event.getX()+90)/180);
                        moveradius(event.getX(), event.getY());
            	    }
            	    else {
            	    	onStartTrackingTouch();
            	    }
                    break;
            case MotionEvent.ACTION_UP:
            	if(mIsDragging) {
                    //drawDot.setColor(mDotColor);
                    //int pos = (int)event.getX()/18;
                    //setDotPosition(8+pos*21);
            		onStopTrackingTouch();
            	} else {
            		onStartTrackingTouch();
            		//rawDot.setColor(mDotColor);
                    //int pos = (int)event.getX()/18;
                    //setDotPosition(8+pos*21);
            		onStopTrackingTouch();
            	}
                invalidate();
                break;
            case MotionEvent.ACTION_CANCEL:
            	if(mIsDragging) {
            		onStopTrackingTouch();
            	}
        		invalidate();
            } 	
            return super.onTouchEvent(event);
    }
   
   /**
    * the interface of ArcSeekbar
    * 
    * @author xiaodong.cheng
    *
    */
   public interface OnSeekBarChangeListener {
       
       /**
        * Notification that the progress level has changed. Clients can use the fromUser parameter
        * to distinguish user-initiated changes from those that occurred programmatically.
        * 
        * @param seekBar The SeekBar whose progress has changed
        * @param progress The current progress level. This will be in the range 0..max where max
        *        was set by {@link ProgressBar#setMax(int)}. (The default value for max is 100.)
        * @param fromUser True if the progress change was initiated by the user.
        */
       void onProgressChanged(RGK_ArcSeekBar seekBar, int progress, boolean fromUser);
   
       /**
        * @param seekBar The SeekBar in which the touch gesture began
        */
       void onStartTrackingTouch(RGK_ArcSeekBar seekBar);
       
       /**
        * @param seekBar The SeekBar in which the touch gesture began
        */
       void onStopTrackingTouch(RGK_ArcSeekBar seekBar);
   }
   
   /**
    * the arcSeekBar listener
    */
   private OnSeekBarChangeListener mOnSeekBarChangeListener;
   
   /**
    * setOnseekBarChangeListerner
    * @param l
    */
   public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
       mOnSeekBarChangeListener = l;
   }
   
   /**
    * onProgressRefresh
    */
   void onProgressRefresh() {
	   
       if (mOnSeekBarChangeListener != null) {
           mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
       }
   }
   
   /**
    * This is called when the user has started touching this widget.
    */
   void onStartTrackingTouch() {
       mIsDragging = true;
       if (mOnSeekBarChangeListener != null) {
           mOnSeekBarChangeListener.onStartTrackingTouch(this);
       }
   }
          
   /**
    * This is called when the user either releases his touch or the touch is
    * canceled.
    */
   void onStopTrackingTouch() {
       mIsDragging = false;
       if (mOnSeekBarChangeListener != null) {
           mOnSeekBarChangeListener.onStopTrackingTouch(this);
       }
   }
   

    // move point to radius
    private void move2radius(float x, float y) {
            angle = (double) buildingradius(x, y);
            postionAngle(angle);
            if (angle > ALL_ARC - ((ALL_ARC - END_ARC) / 2)) {
                    angle = ALL_ARC - ((ALL_ARC - END_ARC) / 2);
            }
            if (angle < ((ALL_ARC - END_ARC) / 2)) {
                    angle = ((ALL_ARC - END_ARC) / 2);
            }

            postionAngle(angle);
            getPoint(angle, 1);
            //add refresh
                onProgressRefresh();
        }
        
 
        //set the ranger of touch-x
    private void moveradius(float x, float y) {
    	if(x < 55*displayRatio || x > 665*displayRatio) {
    		return;
    	}
    	move2radius(x,y);
    }

    // get Point and set Thumb to ARC
    private void getPoint(double thumbradius, int i) {
            if (i == 0) {
                    thumbradius = thumbradius + ((ALL_ARC - END_ARC) / 2);
            }
            float xy[] = goQuadrant(thumbradius);
            if (thumbradius >= 0 && thumbradius < 90) {
                    mThumbX = (float) mCpoint.x - Math.abs(xy[0]);
                    mThumbY = (float) mCpoint.y + Math.abs(xy[1]);
            }
            if (thumbradius >= 90 && thumbradius < 180) {
                    mThumbX = (float) mCpoint.x - Math.abs(xy[0]);
                    mThumbY = (float) mCpoint.y - Math.abs(xy[1]);
            }
            if (thumbradius >= 180 && thumbradius < 270) {
                    mThumbX = (float) mCpoint.x + Math.abs(xy[0]);
                    mThumbY = (float) mCpoint.y - Math.abs(xy[1]);
            }
            if (thumbradius >= 270 && thumbradius < 360) {
                    mThumbX = (float) mCpoint.x + Math.abs(xy[0]);
                    mThumbY = (float) mCpoint.y + Math.abs(xy[1]);
            }
            invalidate();
    }

    // get position
    private void postionAngle(double angle) {
            double mangle = angle - ((ALL_ARC - END_ARC) / 2);
            double proportion = (double) (END_ARC / 100f);
            mDotPosition = (float) (mangle / proportion);
            /*if (listener  != null) {
            	listener.onMove(mDotPosition);
            }*/
    }

    // Get the angle between two points
    private double buildingradius(double x, double y) {
            double temx = Math.abs(x - mCpoint.x);
            double temy = Math.abs(y - mCpoint.y);
            double angle = Math.atan2(temx, temy) * 180 / Math.PI;
            switch (getQuadrant(x, y)) {
            case 2:
                    angle = 180 - angle;
                    break;
            case 3:
                    return angle;
            case 1:
                    angle = angle + 180;
                    break;
            case 4:
                    angle = 360 - angle;
                    break;
            }
            return angle;
    }

    // getPoint Quadrant
    private int getQuadrant(double x, double y) {
            if (mCpoint.x - x >= 0 && mCpoint.y - y >= 0) {
                    return 2;
            }
            if (mCpoint.x - x <= 0 && mCpoint.y - y >= 0) {
                    return 1;
            }
            if (mCpoint.x - x >= 0 && mCpoint.y - y <= 0) {
                    return 3;
            }
            if (mCpoint.x - x <= 0 && mCpoint.y - y <= 0) {
                    return 4;
            }
            return 0;
    }

    // This method can add something
    private boolean isTouchThumb(float x, float y) {
            if (inside(x, y)) {
                    return true;
            }
            return false;
    }

    // if you touch the Thumb can return true else return false
    private boolean inside(float x, float y) {
            Rect r = new Rect((int) (mThumbX - mDotRadius),
                            (int) (mThumbY - mDotRadius), (int) (mThumbX + mDotRadius),
                            (int) (mThumbY + mDotRadius));
            if (r.contains((int) x, (int) y)) {
                    return true;
            }
            return false;
    }

    /**
     * set the arcseekbar's background
     * @param line
     */
    public void setLine(Drawable line) {
    	this.mLine = line;
//    	if(!isEnabled()) {
//    		mLine.setColorFilter(Color.GRAY,PorterDuff.Mode.MULTIPLY);
//    	}else {
//    		mLine.clearColorFilter();
//    	}
    	//invalidate();
    }
    
    /**
     * set the arcseekbar's thumb icon
     * @param icon
     */
    public void setIcon(Drawable icon) {
    	this.mIcon = icon;
//    	if(!isEnabled()) {
//    	    mIcon.setColorFilter(Color.GRAY,PorterDuff.Mode.MULTIPLY);
//    	}else {
//    		mLine.clearColorFilter();
//    	}
    	mIconBitmap = ((BitmapDrawable)mIcon).getBitmap();
    	//invalidate();
    }
    
    public void setIconBitmap(Bitmap iconBitmap) {
    	this.mIconBitmap = iconBitmap;
    }
    
    @SuppressLint("DrawAllocation")
	@Override
    protected void onDraw(Canvas canvas) {
//            canvas.drawCircle(mCpoint.x, mCpoint.y, mCircleradius, drawCircle);
//            canvas.drawArc(rectF, START_ARC, END_ARC, false, drawArc);
    	    Rect rect = new Rect(0,0,(int)(720*displayRatio+f),(int)(154*displayRatio+f));
            Bitmap bitmap1 = ((BitmapDrawable)mLine).getBitmap();
            canvas.drawBitmap(bitmap1, null, rect, null);    
    	    canvas.save();
//            if (isNeedShaper) {
//            	LinearGradient gradient = new LinearGradient(xy[0], xy[1], mThumbX,
//                                    mThumbY, fromColor, toColor, TileMode.MIRROR);
//                    drawArcShaper.setShader(gradient);
//                    // canvas.drawArc(rectF, (float) angle - 45, END_ARC, false,
//                    // drawArc);
//                        if (angle != 0) {
//                                canvas.drawArc(rectF, START_ARC, (float) angle - 45, false,
//                                                drawArcShaper);
//                        } else {
//                                canvas.drawArc(rectF, START_ARC, (float) angle, false,
//                                                drawArcShaper);
//                        }
//                }
//                canvas.drawCircle(mThumbX, mThumbY, mDotRadius, drawDot);
//                
//                paint_string.setColor(Color.BLACK);
//                paint_string.setTextSize(40);
//                canvas.drawText(flag,mThumbX-30,mThumbY+15,paint_string);
    	    //Bitmap bitmap = ((BitmapDrawable)mIcon).getBitmap();
            canvas.drawBitmap(mIconBitmap, (int)(mThumbX-46*displayRatio+f), (int)(mThumbY-46*displayRatio+f), null);
    	    canvas.restore();
            super.onDraw(canvas);
    }

 
        /**
     * CenterPoint
     * 
     * @author xiaodong.cheng
     * 
     */
    public static class CenterPoint {
            public int x;
            public int y;
            public int w;
            public int h;
    }

    /*public interface OnSeekMoveListener {
    	public void onMove(float f);
    }

    private OnSeekMoveListener  listener;


    public void setOnSeekMovtener(OnSeekMoveListener listener) {
            this.listener =listener;
    }*/
    
    /**
     * the seekbar's flag
     * 
     * @param flag
     */
    public void setFlag(String flag) {
    	this.flag = flag;
    }
        

}
